package io.chenglicun.modules.clc.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.chenglicun.common.page.PageData;
import io.chenglicun.common.service.impl.CrudServiceImpl;
import io.chenglicun.common.constant.Constant;
import io.chenglicun.modules.clc.dao.ClcMapNodeInfoDao;
import io.chenglicun.modules.clc.dto.ClcMapNodeCoordinateDTO;
import io.chenglicun.modules.clc.dto.ClcMapNodeInfoDTO;
import io.chenglicun.modules.clc.entity.ClcMapNodeCoordinateEntity;
import io.chenglicun.modules.clc.entity.ClcMapNodeInfoEntity;
import io.chenglicun.modules.clc.service.ClcMapNodeCoordinateService;
import io.chenglicun.modules.clc.service.ClcMapNodeInfoService;
import io.chenglicun.modules.security.user.SecurityUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数字地图节点信息
 *
 * @author HB 137664951@qq.com
 * @since 1.0 2023-11-06
 */
@Service
public class ClcMapNodeInfoServiceImpl extends CrudServiceImpl<ClcMapNodeInfoDao, ClcMapNodeInfoEntity, ClcMapNodeInfoDTO> implements ClcMapNodeInfoService {

    @Autowired
    private ClcMapNodeCoordinateService coordinateService;

    @Override
    public Map<String, Object> getList() {
        QueryWrapper<ClcMapNodeInfoEntity> wrapper = new QueryWrapper<>();
        List<ClcMapNodeInfoEntity> entities = baseDao.selectList(wrapper);
        List<String> collect = entities.stream().map(ClcMapNodeInfoEntity::getJsonInfo).collect(Collectors.toList());

        List<Object> list = new ArrayList<>(collect.size());
        collect.forEach(t -> list.add(JSONObject.parseObject(t)));
        Map<String, Object> map = new HashMap<>();
        map.put("type", "FeatureCollection");
        map.put("features", list);

        return map;
    }

    @Override
    public Object getInfo(String pointId) {
        QueryWrapper<ClcMapNodeInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ClcMapNodeInfoEntity::getPointId, pointId).last("limit 1");
        ClcMapNodeInfoEntity entity = baseDao.selectOne(wrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("type", "Feature");
        map.put("pointId", entity.getPointId());
        map.put("deptId", entity.getDeptId());
        map.put("jsonInfo", JSONObject.parseObject(entity.getJsonInfo()));

        return map;
    }

    @Override
    public void deleteByPointIds(Long[] ids) {
        QueryWrapper<ClcMapNodeInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.in("point_id", ids);
        baseDao.delete(wrapper);
    }

    @Override
    public QueryWrapper<ClcMapNodeInfoEntity> getWrapper(Map<String, Object> params){
        QueryWrapper<ClcMapNodeInfoEntity> wrapper = new QueryWrapper<>();

        Object sourceId = params.get("sourceId");
        wrapper.eq(ObjectUtil.isNotEmpty(sourceId), "source_id", sourceId);
        Object sourceType = params.get("sourceType");
        wrapper.eq(ObjectUtil.isNotEmpty(sourceType), "source_type", sourceType);
        Object annotationType = params.get("annotationType");
        wrapper.eq(ObjectUtil.isNotEmpty(annotationType), "annotation_type", annotationType);

        return wrapper;
    }

    @Override
    public PageData<ClcMapNodeInfoDTO> page(Map<String, Object> params) {
        PageData<ClcMapNodeInfoDTO> page = super.page(params);
        List<ClcMapNodeInfoDTO> list = page.getList();
        this.setData(list.toArray(new ClcMapNodeInfoDTO[0]));
        return page;
    }

    @Override
    public List<ClcMapNodeInfoDTO> list(Map<String, Object> params) {
        List<ClcMapNodeInfoDTO> list = super.list(params);
        this.setData(list.toArray(new ClcMapNodeInfoDTO[0]));
        return list;
    }

    @Override
    public ClcMapNodeInfoDTO get(Long id) {
        ClcMapNodeInfoDTO dto = super.get(id);
        this.setData(dto);
        return dto;
    }

    private void setData(ClcMapNodeInfoDTO... dtos) {
        if (dtos.length == 0) return;
        Long[] ids = Arrays.stream(dtos).map(ClcMapNodeInfoDTO::getId).toArray(Long[]::new);
        List<ClcMapNodeCoordinateDTO> coordinateDTOS = coordinateService.getByInfoIds(ids);

        for (ClcMapNodeInfoDTO dto : dtos) {
            List<BigDecimal> coordinates = coordinateDTOS.stream().filter(t -> t.getMapNodeInfoId().equals(dto.getId())).map(ClcMapNodeCoordinateDTO::getCoordinateValue).collect(Collectors.toList());
            dto.setCoordinates(coordinates);
        }
    }

    @Override
    @Transactional
    public void save(ClcMapNodeInfoDTO dto) {
        super.save(dto);

        List<BigDecimal> coordinates = dto.getCoordinates();
        if (coordinates != null) {
            List<ClcMapNodeCoordinateEntity> coordinateEntities = new ArrayList<>(coordinates.size());
            for (int i = 0; i < coordinates.size(); i++) {
                BigDecimal t = coordinates.get(i);
                ClcMapNodeCoordinateEntity coordinateEntity = new ClcMapNodeCoordinateEntity();
                coordinateEntity.setMapNodeInfoId(dto.getId());
                coordinateEntity.setNo(i);
                coordinateEntity.setCoordinateValue(t);
                coordinateEntities.add(coordinateEntity);
            }
            coordinateService.insertBatch(coordinateEntities);
        }
    }

    @Override
    @Transactional
    public void update(ClcMapNodeInfoDTO dto) {
        super.update(dto);

        coordinateService.deleteByInfoIds(dto.getId());

        List<BigDecimal> coordinates = dto.getCoordinates();
        List<ClcMapNodeCoordinateEntity> coordinateEntities = new ArrayList<>(coordinates.size());
        for (int i = 0; i < coordinates.size(); i++) {
            BigDecimal t = coordinates.get(i);
            ClcMapNodeCoordinateEntity coordinateEntity = new ClcMapNodeCoordinateEntity();
            coordinateEntity.setMapNodeInfoId(dto.getId());
            coordinateEntity.setNo(i);
            coordinateEntity.setCoordinateValue(t);
            coordinateEntities.add(coordinateEntity);
        }
        coordinateService.insertBatch(coordinateEntities);
    }

    @Override
    @Transactional
    public void delete(Long[] ids) {
        super.delete(ids);
        coordinateService.deleteByInfoIds(ids);
    }
}